import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { RoleEnum } from 'src/constants/role';
import { In, Repository } from 'typeorm';
import { ResourceEntity } from '../resource/entities/resource.entity';
import { ResourceRoleEntity } from '../resource/entities/resource.role.entity';
import { BindAclDto } from './dto/bind.acl.dto';
import { createRoleDto } from './dto/create.role.dto';
import { RoleListDto } from './dto/role.list.dto';
import { RoleEntity } from './entities/role.entity';

@Injectable()
export class RoleService {
  constructor(
    @InjectRepository(RoleEntity)
    private readonly roleRepository: Repository<RoleEntity>,
    @InjectRepository(ResourceEntity)
    private readonly resourceRepositoty: Repository<ResourceEntity>,
    @InjectRepository(ResourceRoleEntity)
    private readonly resourceRoleRepository: Repository<ResourceRoleEntity>,
  ) {}
  /**
   * @Author: laotongshu
   * @Date: 2022-10-10 11:02:45
   * @LastEditors: laotongshu
   * @Description: 创建角色
   * @param {Object} {}
   * @return {*}
   */
  async createRole(createRoleDto: createRoleDto): Promise<string> {
    const { name, isDefault } = createRoleDto;
    const findNameResult: Pick<RoleEntity, 'id'> = await this.roleRepository.findOne({
      where: { name },
      select: ['id'],
    });
    if (findNameResult) {
      return `当前角色已经存在,不能重复创建`;
    }
    // 如果是默认角色的时候要判断下
    if (Object.is(isDefault, RoleEnum.DEFAULT)) {
      const findDefault: Pick<RoleEntity, 'id'> | undefined = await this.roleRepository.findOne({
        where: { isDefault },
        select: ['id'],
      });
      if (findDefault) {
        return '已经存在默认角色不能重复创建';
      }
    }
    const role: RoleEntity = this.roleRepository.create(createRoleDto);
    await this.roleRepository.save(role);
    return '创建角色成功';
  }
  // 获取权限列表（分页）
  async getRole(roleDto: RoleListDto) {
    let { currentPage = 1, pageSize = 20 } = roleDto;
    currentPage = Number(currentPage);
    pageSize = Number(pageSize);
    const list = await this.roleRepository.find({
      skip: (currentPage - 1) * pageSize,
      take: pageSize,
    });
    const total = await this.roleRepository.count();
    return {
      data: list,
      total,
    };
  }

  /**
   * @Author: laotongshu
   * @Date: 2022-10-10 17:00:50
   * @LastEditors: laotongshu
   * @Description: 给角色绑定权限
   * @param {Object} {}
   * @return {*}
   */
  async bindAccess(id: string, bindAclDto: BindAclDto) {
    const role = await this.roleRepository.findOneByOrFail({ id });
    const acls = await this.resourceRepositoty.find({
      where: {
        id: In(bindAclDto.acls),
      },
    });
    const roleAclsPromise = acls.map(async (acl) => {
      let roleAcl = await this.resourceRoleRepository.findOne({
        where: {
          resourceId: acl.id,
          roleId: role.id,
        },
      });
      if (!roleAcl) {
        roleAcl = new ResourceRoleEntity();
        roleAcl.resourceId = acl.id;
        roleAcl.roleId = role.id;
      }
      return roleAcl;
    });
    const roleAcls = await Promise.all(roleAclsPromise);
    role.roleResource = roleAcls;
    return this.roleRepository.save(role);
  }
}
